package jmine.tec.executionlog.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import jmine.tec.executionlog.domain.enumx.ExecutionItemStatus;
import jmine.tec.persist.annotation.Alias;
import jmine.tec.persist.annotation.Constraint;
import jmine.tec.persist.annotation.Index;
import jmine.tec.persist.schema.api.IndexOrder;
import jmine.tec.services.io.ServiceBean;

import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Type;

import bancosys.tec.component.Documentation;
import bancosys.tec.persist.bussobj.PersistableBusinessObject;

/**
 * Item de log de execucao.
 * 
 * @author Marcio Ribeiro (mmr)
 * @created Jun 19, 2008
 */
@Entity
@Table(name = "EXECUTION_LOG_ITEM")
@Alias("EXELOI")
@SequenceGenerator(name = "SEQ_EXELOI", sequenceName = "SEQ_EXELOI")
@Documentation("ARMAZENA DETALHES DE LOG DO PROCESSO DE IMPORTACAO DE ARQUIVOS DO TIPO PLANILHA DE SERVICOS.")
public class ExecutionLogItem extends PersistableBusinessObject implements Comparable<ExecutionLogItem> {
    private static final long serialVersionUID = -8481090849478446279L;

    private Long id;

    private String content;

    private ExecutionItemStatus status;

    private String message;

    private String stackTrace;

    private ExecutionLog executionLog;

    /**
     * @return o id.
     */
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_EXELOI")
    @Column(name = "COD_EXECUTION_LOG_ITEM", nullable = false)
    @Documentation("CODIGO DO ITEM DO LOG DE EXECUÇÃO.")
    public Long getId() {
        return this.id;
    }

    /**
     * Define o id.
     * 
     * @param id o id.
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return log de execucao.
     */
    @ManyToOne
    @JoinColumn(name = "COD_EXECUTION_LOG", nullable = false)
    @ForeignKey(name = "FK_EXELOG_EXELOI")
    @Index(columns = "COD_EXECUTION_LOG", suffix = "0", orders = IndexOrder.ASC)
    @Documentation("CODIGO DO LOG DE EXECUÇÃO AO QUAL ESTE ITEM PERTENCE.")
    public ExecutionLog getExecutionLog() {
        return this.executionLog;
    }

    /**
     * Define log de execucao pai desse item.
     * 
     * @param executionLog log de execucao.
     */
    public void setExecutionLog(ExecutionLog executionLog) {
        this.executionLog = executionLog;
    }

    /**
     * @return dados de item de execucao.
     */
    @Lob
    @Column(name = "CONTENT")
    @Type(type = "org.hibernate.type.TextType")
    @Documentation("CONTEÚDO DO ITEM DO LOG DE EXECUÇÃO. PODE CONTER UMA LINHA OU TRECHO DO ARQUIVO, "
            + "OU AINDA UM REGISTRO NUM FORMATO ESPECÍFICO DO SISTEMA.")
    public String getContent() {
        return this.content;
    }

    /**
     * Define dados de log de item de execucao.
     * 
     * @param content dados de item de execucao.
     */
    public void setContent(String content) {
        this.content = content;
    }

    /**
     * @return status de item de execucao.
     */
    @Column(name = "ST")
    @Documentation("STATUS DA EXECUÇÃO DO ITEM DA INTEGRAÇÃO. 0. OK; "
            + "1. ERRO; 2. NÃO EXECUTADO; 3. ITEM INSERIDO; 4. ITEM ATUALIZADO; 5. EXECUTADO COM ALERTAS; 6. ITEM IGNORADO.")
    @Constraint(suffix = "0")
    public ExecutionItemStatus getStatus() {
        return this.status;
    }

    /**
     * Define status de item de execucao.
     * 
     * @param status status de item de execucao.
     */
    public void setStatus(ExecutionItemStatus status) {
        this.status = status;
    }

    /**
     * Devolve a mensagem que descreve esse item.
     * 
     * @return a mensagem que descreve esse item.
     */
    @Lob
    @Column(name = "MSG")
    @Type(type = "org.hibernate.type.TextType")
    @Documentation("MENSAGEM QUE DESCREVE O ITEM OU O STATUS DA EXECUÇÃO DO ITEM.")
    public String getMessage() {
        return this.message;
    }

    /**
     * Define a mensagem que descreve esse item.
     * 
     * @param message a mensagem que descreve esse item.
     */
    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * @return the stackTrace
     */
    @Lob
    @Column(name = "STACK")
    @Type(type = "org.hibernate.type.TextType")
    @Documentation("LOG DE ERRO/ALERTA DA EXECUÇÃO DO ITEM.")
    public String getStackTrace() {
        return this.stackTrace;
    }

    /**
     * @param stackTrace the stackTrace to set
     */
    public void setStackTrace(String stackTrace) {
        this.stackTrace = stackTrace;
    }

    /**
     * @return <code>true</code> se status de item de execucao for OK, <code>false</code> se nao.
     */
    @Transient
    public boolean isOk() {
        return ExecutionItemStatus.OK.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de item de execucao for NAO OK, <code>false</code> se nao.
     */
    @Transient
    public boolean isNotOk() {
        return ExecutionItemStatus.NOT_OK.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de item de execucao for de Inserção, <code>false</code> se nao.
     */
    @Transient
    public boolean isInsert() {
        return ExecutionItemStatus.INSERT.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de item de execucao for de Alteraçao, <code>false</code> se nao.
     */
    @Transient
    public boolean isUpdate() {
        return ExecutionItemStatus.UPDATE.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de item de execucao for de Alerta, <code>false</code> se nao.
     */
    @Transient
    public boolean isAlert() {
        return ExecutionItemStatus.ALERT.equals(this.status);
    }

    /**
     * @return <code>true</code> se status de item de execucao for de Ignore, <code>false</code> se nao.
     */
    @Transient
    public boolean isIgnore() {
        return ExecutionItemStatus.IGNORE.equals(this.status);
    }

    /**
     * {@inheritDoc}
     */
    public int compareTo(ExecutionLogItem o) {
        return (this.getId() - o.getId() < 0) ? -1 : (this.getId().equals(o.getId()) ? 0 : 1);
    }

    /**
     * Transforma o conteudo do log em um {@link ServiceBean} e recupera a localização do serviço.
     * 
     * @return a localização do serviço contido no conteudo do log.
     */
    @Transient
    public String getServiceLocation() {
        return ServiceBean.fromXml(this.getContent()).getServiceLocation();
    }
}
